package de.bht.fb6.mobisand.avoidlist.persistence.local;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import de.bht.fb6.mobisand.avoidlist.model.ToAvoid;

/**
 * Kümmert sich um die Verwaltung der ToDos auf dem Gerät.
 * Dazu wird eine SQLite Datenbank verwendet.
 * 
 * @author Bruno Kirschner, Mario Dörwald
 * @since 09. Jan 2013
 */
public class LocalToAvoidHandler {

	///////////////////// Attribute //////////////////////////////////////////////////////////////
	
	/** Name der Datenbank **/
	private static final String DB_NAME = "ToAvoidList";
	
	/** Datenbank objekt **/
	private SQLiteDatabase database;
	
	/** Hilfsklasse zum Öffnen der Datenbank **/
	private LocalDatabaseOpenHelper dpOpenHelper;
	
	////////////////////// Konstruktoren /////////////////////////////////////////////////////////
	
	/**
	 * Konstruktor dem der Context übergeben wird in dem gearbeitet werden soll.
	 * (Meist der Context der Activity die den Konstruktor aufruft)
	 * 
	 * @param context
	 * 	Context mit dessen Hilfe die Hilfsklasse initialisiert wird
	 */
    public LocalToAvoidHandler(Context context) {
    	this.dpOpenHelper = new LocalDatabaseOpenHelper(context, DB_NAME, null, 1);
	}
    
    ////////////////////// öffentliche Methoden /////////////////////////////////////////////////////
    
    /**
     * Öffnet eine Datenbankverbindung.
     * 
     * @throws SQLException
     * 	Sollte beim Öffenen der Datenbankverbindung ein Fehler aufgetreten sein.
     */
	public void open() throws SQLException {
		this.database = this.dpOpenHelper.getWritableDatabase();
	}
	
	/**
	 * Schließt die aktuelle Datenbankverbindung.
	 */
	public void close() {
		if (this.database != null) {
			this.database.close();
		}
	}
	
	/**
	 * Fügt ein ToAvoid in die Datenbank ein.
	 * 
	 * @param toAvoid
	 * 	Das ToAvoid Element das in die Datenbank eingefügt werden soll.
	 */
	public void insertToAvoid(final ToAvoid toAvoid) {
		this.open();
		/**
		 * Fügt in die angegebene Tabelle das übergebene ContentValue element ein
		 * Der mittlereParameter ist optional und wird nur genutzt, falls eine komplett
		 * leere Reihe in die Datenbank eingefügt werden soll.
		 **/
		this.database.insert(LocalDatabaseOpenHelper.TABLE_NAME, null, createContentValues(toAvoid));
		this.close();
	}
	
	/**
	 * Aktualisiert ein bereits in der Datenbank vorhandenes ToAvoid.
	 * 
	 * @param toAvoid
	 * 	Das ToAvoid Element das in der Datenbank aktualisiert werden soll.
	 */
	public void updateToAvoid(final ToAvoid toAvoid) {
		this.open();
		/**
		 * Aktualisiert den als Parameter übergebene ToAvoid in der hier aufgefügten Tabelle ein.
		 * mit Hilfe der ID wird hier angegeben welche Reihe aktualisiert werden soll.
		 */
		this.database.update(LocalDatabaseOpenHelper.TABLE_NAME, createContentValues(toAvoid), "_id = ?", new String[] {""+toAvoid.getId()});
		this.close();
	}
	
	/**
	 * Führt einen Query aus um alle ToAvoid aus der Datenbank auszulesen.
	 * Liefert anschließend einen Cursor auf das Ergebniss des Querys zurück.
	 * 
	 * @return
	 * 	Liste aller in der Datenbank enthaltenen ToAvoid Elemente
	 */
	public List<ToAvoid> getAllToAvoids () {
		this.open();
		/**
		 * 1. Parameter: Query auf die hier aufgeführte Tabelle.
		 * 2. Parameter: Spalten die nachgefragt werden.
		 * 3. Parameter: Optionaler Filter für spezielle Reihen
		 * 4. Parameter: Argumente für den 3. Parameter
		 * 5. Parameter: Filter um einzelne Spalten zu gruppieren
		 * 6. Parameter: Filter der angibt welche Spaltengruppen zurückgegeben werden sollen.
		 * 7. Parameter: Spalte nach der Sortiert werden soll
		 * 8. Parameter: Limit für die Anzahl der zurückgegebenen Reihen
		 */
		Cursor cur = this.database.query(LocalDatabaseOpenHelper.TABLE_NAME, new String[] {"_id", "name", "description", "avoided", "importance", "avoidanceDate"}, null, null, null, null, "_id", null);
		List<ToAvoid> ret = new ArrayList<ToAvoid>();
		
		if(cur.moveToFirst()) {
			ToAvoid generatedToAvoid = null;
			
			do {
				generatedToAvoid = this.generateToAvoid(cur);
				
				if(generatedToAvoid != null) {
					ret.add(generatedToAvoid);
				}
			} while (cur.moveToNext());
		}
		cur.close();
		
		this.close();
		return ret; 
	}
	
	/**
	 * Liest ein einzelnes ToAvoid Element anhand seiner ID aus der Datenbank aus.
	 * 
	 * @param id
	 * 	id des ToAvoid Elementes das ausgelesen werden soll.
	 * @return
	 * 	Cursor auf das Ergebnis des Querys nach der speziellen ID
	 */
	public ToAvoid getSingleToAvoid (long id) {
		this.open();
		
		Cursor cur = database.query("toAvoid", null, "_id = ?", new String[] {""+id}, null, null, null);
		ToAvoid generatedToAvoid = generateToAvoid(cur);
		cur.close();
		
		this.close();
		return generatedToAvoid;
    }
	
	/**
	 * Löscht ein ToAvoid Element anhand seiner ID aus der Datenbank.
	 * 
	 * @param id
	 * 	id des ToAvoid Elementes das aus der Datenbank gelöscht werden soll.
	 */
	public void deleteToAvoid (final long id) {
	   this.open();
	   
	   /**
	    * Tabelle der Datenbank in der eine Reihe entsprechend des 2. Parameters gelöscht werden soll.
	    */
	   this.database.delete(LocalDatabaseOpenHelper.TABLE_NAME, "_id = ?", new String[] {""+id});
	   this.close();
   }
	
	/////////////////////////////// prviate Methoden //////////////////////////////////////////////////
	
	/**
	 * Methode um aus einem ToAvoid ein Element des Typs "ContentValues"
	 * zu erzeugen. Dieses wird benötigt um die Daten in die Datenbank zu überführen.
	 * 
	 * @param toAvoid
	 * 	ToAvoid Element das überführt werden soll.
	 * @return
	 * 	ContentValues Element das dem ToAvoidElement entspricht
	 */
	private ContentValues createContentValues(final ToAvoid toAvoid) {
		ContentValues conVals = new ContentValues();
		
		conVals.put("avoided", toAvoid.isAvoided());
		conVals.put("avoidanceDate", toAvoid.getAvoidanceDate().toString());
		conVals.put("description", toAvoid.getDescription());
		conVals.put("importance", toAvoid.getImportance());
		conVals.put("name", toAvoid.getName());
		
		return conVals;
	}
	
	/**
	 * Erzeugt aus einem übergebenen Cursor auf ein Queryergebniss ein ToAvoid Element.
	 * 
	 * @param cursor
	 * 	der Cursor der auf die Daten zeigt.
	 * @return
	 * 	das erstellte ToAvoid Element
	 */
	private ToAvoid generateToAvoid(Cursor cursor) {
		ToAvoid ret = new ToAvoid();
		
		if (cursor.getColumnIndex("_id") != -1) {
			ret.setId(cursor.getInt(cursor.getColumnIndex("_id")));
		}
		
		if (cursor.getColumnIndex("avoided") != -1) {
			ret.setAvoided(Boolean.getBoolean(cursor.getString(cursor.getColumnIndex("avoided"))));
		}
		
		if (cursor.getColumnIndex("avoidanceDate") != -1) {
			// #ToDo sollte irgendwo als allgemeingültiges Format gespeichert werden
			//DateFormat df = SimpleDateFormat.getDateInstance(SimpleDateFormat.DEFAULT, Locale.GERMAN);
			
			ret.setAvoidanceDate(new Date(Date.parse(cursor.getString(cursor.getColumnIndex("avoidanceDate")))));
		}
		
		if (cursor.getColumnIndex("description") != -1) {
			ret.setDescription(cursor.getString(cursor.getColumnIndex("description")));
		}
		
		if (cursor.getColumnIndex("name") != -1) {
			ret.setImportance(cursor.getInt(cursor.getColumnIndex("importance")));
		}
		
		if (cursor.getColumnIndex("name") != -1) {
			ret.setName(cursor.getString(cursor.getColumnIndex("name")));
		}
		
		return ret;
	}
}